#include <sw/redis++/redis.h>
#include <iostream>
#include <chrono>
#include <thread>

using std::cout;
using std::endl;
using sw::redis::Redis;
using namespace std::chrono_literals;

void test1(Redis &redis)
{
    cout << "set and get" << endl;
    redis.flushall();

    redis.set("key", "111");
    auto ret = redis.get("key");
    if (ret)
        cout << ret.value() << endl;

    redis.set("key", "233");
    ret = redis.get("key");
    if (ret)
        cout << ret.value() << endl;
}

void test2(Redis &redis)
{
    cout << "set with expire" << endl;
    redis.flushall();

    redis.set("key", "233", std::chrono::seconds(10));

    std::this_thread::sleep_for(std::chrono::seconds(3));

    auto ret = redis.ttl("key");
    cout << ret << endl;
}

void test3(Redis &redis)
{
    cout << "set NX and XX" << endl;
    redis.flushall();

    redis.set("key", "233", 0s, sw::redis::UpdateType::NOT_EXIST);
    auto value = redis.get("key");
    if (value)
        cout << "value: " << value.value() << endl;
    else
        cout << "value 不存在" << endl;

    // redis.set("key", "666", 0s, sw::redis::UpdateType::NOT_EXIST);
    redis.set("key", "666", 0s, sw::redis::UpdateType::EXIST);
    value = redis.get("key");
    if (value)
        cout << "value: " << value.value() << endl;
    else
        cout << "value 不存在" << endl;
}

void test4(Redis &redis)
{
    std::cout << "mset" << endl;
    redis.flushall();

    // 初始化列表
    // redis.mset({std::make_pair("key1","111"),std::make_pair("key2","222"),std::make_pair("key3","333")});

    // 存到容器中再用迭代器的方式使用
    std::vector<std::pair<std::string, std::string>> keys = {
        {"key1", "111"},
        {"key2", "222"},
        {"key3", "333"}};
    redis.mset(keys.begin(), keys.end());

    auto value = redis.get("key1");
    if (value)
        cout << value.value() << endl;

    value = redis.get("key2");
    if (value)
        cout << value.value() << endl;

    value = redis.get("key3");
    if (value)
        cout << value.value() << endl;
}

void test5(Redis &redis)
{
    std::cout << "mget" << endl;
    redis.flushall();

    std::vector<std::pair<std::string, std::string>> keys = {
        {"key1", "111"},
        {"key2", "222"},
        {"key3", "333"}};
    redis.mset(keys.begin(), keys.end());

    std::vector<sw::redis::OptionalString> values;
    auto it = std::back_inserter(values);
    redis.mget({"key1", "key2", "key3"}, it);

    for (int i = 0; i < values.size(); ++i)
        if (values[i])
            cout << values[i].value() << endl;
}

void test6(Redis &redis)
{
    cout << "getrange and setrange" << endl;
    redis.flushall();

    redis.set("key", "abcdefg123456");
    std::string ret = redis.getrange("key", 4, -1);

    cout << ret << endl;

    redis.setrange("key", 2, "alpaca");
    auto value = redis.get("key");

    cout << value.value() << endl;
}

void test7(Redis &redis)
{
    cout << "incr and decr" << endl;
    redis.flushall();

    redis.set("key", "214");
    long long result = redis.incr("key");
    cout << result << endl;
    auto value = redis.get("key");
    if (value)
        cout << value.value() << endl;

    result = redis.decr("key");
    cout << result << endl;
    value = redis.get("key");
    if (value)
        cout << value.value() << endl;
}

int main()
{
    Redis redis("tcp://127.0.0.1:6379");

    // test1(redis);
    // test2(redis);
    // test3(redis);
    // test4(redis);
    // test5(redis);
    // test6(redis);
    test7(redis);

    return 0;
}